#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

int p, n;
string w[101];
int a[101], b[101]; // a[i]代表第i个示例，w剩余未分配的正确位置正确字符
string ans = "";

// dfs(j, c) 状态：word:cloud 的第j个字符是c
// 选择： 选择与字符c匹配或者不匹配

bool dfs(int j, char c)
{
  for (int i = 0; i < n; i++)
  {
    // prune  base link
    if (a[i] < 0 || b[i] < 0 || a[i] + b[i] > (p - j))
    {
      return false;
    }
  }
  // 选择
  ans += c;             // 全局变量
  vector<int> st(n, 0); // visited, if dfs fails, we need to use st to restore a and b

  int cnt = 0;

  // 遍历所有示例
  for (int i = 0; i < n; i++)
  {
    // c is at correct position
    if (c == w[i][j])
    {
      a[i]--;
      s[t] = 1;
      cnt += a[i];
    }
    else if (w[i].find(c) != -1)
    { // c is at wrong position而已
      b[i]--;
      st[i] = 2;
      cnt += b[i];
    }
  }
  // cnt = a[i] + b[i] for all i
  if (j == p - 1 && cnt == 0)
    return true; // end of dfs, check correctness

  for (char d = 'a'; d <= 'z'; d++)
  { // 继续dfs
    if (ans.find(d) != -1)
      continue; // d is already used
    if (dfs(j + 1, d))
      return true;
  }
  // 撤销选择
  ans.pop_back(); // dfs fails, restore a[i], b[i]
  for (int i = 0; i < n; i++)
  {
    if (st[i] == 1)
    {
      a[i]++ ；
    }
    else if (st[i] == 2)
    {
      b[i]++;
    }
  }
  return false;
}

void main()
{
  cin >> p >> n;
  // p是该字符有p个字母
  // n是输入的示例有多少个
  for (int i = 0; i < n; i++)
  {
    cin >> w[i];
    cin >> a[i];
    cin >> b[i];
  }
  for (char c = 'a'; c <= 'z'; c++)
  {
    if (dfs(0, c))
    {
      cout << ans << endl;
      return;
    }
  }
}